﻿#include "TestDynMemPool.h"
#include "CDynMemPool.h"
#include <iostream>

TestDynMemPool::TestDynMemPool()
{
	size_t pos = 0;
	memset(this->m_pObj1, 0, sizeof(this->m_pObj1));
	memset(this->m_pObj2, 0, sizeof(this->m_pObj2));
	memset(this->m_pObj3, 0, sizeof(this->m_pObj3));
	memset(this->m_pObj4, 0, sizeof(this->m_pObj4));
}

TestDynMemPool::~TestDynMemPool()
{
	this->Dealloc(__TYPE_EVERY, false);
}

/// 分配空间
void TestDynMemPool::Alloc(int type, bool pool)
{
	size_t num = 1;
	size_t choose = 0;

	switch(type)
	{
	case __TYPE_RAND:
		{
			/// 1 ~ 5
			num = (rand() % 5) + 1;
			choose = (rand() % 4) + 1;
		}
		break;
	case __TYPE_EVERY:
		{
			num = 1;
			choose = 0;
		};
		break;
	default:
		return;
	}

	if(choose == 0)
	{
		size_t pos = 0;
		for(; pos < obj_num[0]; ++pos)
		{
			if(this->m_pObj1[pos])
			{
				continue;
			}
			if(pool)
			{
				this->m_pObj1[pos] = (TestObj_1*)CDynMemPool::GetInstance().Allocate(sizeof(TestObj_1));
			}
			else
			{
				this->m_pObj1[pos] = (TestObj_1*)malloc(sizeof(TestObj_1));
			}
			if(!this->m_pObj1[pos])
			{
				std::cout << "[TestDynMemPool] error in Allocate" << std::endl;
				continue;
			}
			this->m_pObj1[pos]->setValue(1000000 + pos);
		}

		pos = 0;
		for(; pos < obj_num[1]; ++pos)
		{
			if(this->m_pObj2[pos])
			{
				continue;
			}
			if(pool)
			{
				this->m_pObj2[pos] = (TestObj_2*)CDynMemPool::GetInstance().Allocate(sizeof(TestObj_2));
			}
			else
			{
				this->m_pObj2[pos] = (TestObj_2*)malloc(sizeof(TestObj_2));
			}
			if(!this->m_pObj2[pos])
			{
				std::cout << "[TestDynMemPool] error in Allocate" << std::endl;
				continue;
			}
			this->m_pObj2[pos]->setValue(2000000 + pos);
		}

		pos = 0;
		for(; pos < obj_num[2]; ++pos)
		{
			if(this->m_pObj3[pos])
			{
				continue;
			}
			if(pool)
			{
				this->m_pObj3[pos] = (TestObj_3*)CDynMemPool::GetInstance().Allocate(sizeof(TestObj_3));
			}
			else
			{
				this->m_pObj3[pos] = (TestObj_3*)malloc(sizeof(TestObj_3));
			}
			if(!this->m_pObj3[pos])
			{
				std::cout << "[TestDynMemPool] error in Allocate" << std::endl;
				continue;
			}
			this->m_pObj3[pos]->setValue(3000000 + pos);
		}

		pos = 0;
		for(; pos < obj_num[3]; ++pos)
		{
			if(this->m_pObj4[pos])
			{
				continue;
			}
			if(pool)
			{
				this->m_pObj4[pos] = (TestObj_4*)CDynMemPool::GetInstance().Allocate(sizeof(TestObj_4));
			}
			else
			{
				this->m_pObj4[pos] = (TestObj_4*)malloc(sizeof(TestObj_4));
			}
			if(!this->m_pObj4[pos])
			{
				std::cout << "[TestDynMemPool] error in Allocate" << std::endl;
				continue;
			}
			this->m_pObj4[pos]->setValue(4000000 + pos);
		}
	}
	else
	{
		/// 每个都做
		size_t pos = 0;
		for(; pos < obj_num[choose-1]; ++pos)
		{
			if(pos % num != 0)
			{
				continue;
			}

			switch(choose)
			{
			case 1:
				{
					if(this->m_pObj1[pos])
					{
						continue;
					}
					if(pool)
					{
						this->m_pObj1[pos] = (TestObj_1*)CDynMemPool::GetInstance().Allocate(sizeof(TestObj_1));
					}
					else
					{
						this->m_pObj1[pos] = (TestObj_1*)malloc(sizeof(TestObj_1));
					}
					if(!this->m_pObj1[pos])
					{
						std::cout << "[TestDynMemPool] error in Allocate" << std::endl;
						continue;
					}
					this->m_pObj1[pos]->setValue(1000000 + pos);
				}
				break;
			case 2:
				{
					if(this->m_pObj2[pos])
					{
						continue;
					}
					if(pool)
					{
						this->m_pObj2[pos] = (TestObj_2*)CDynMemPool::GetInstance().Allocate(sizeof(TestObj_2));
					}
					else
					{
						this->m_pObj2[pos] = (TestObj_2*)malloc(sizeof(TestObj_2));
					}
					if(!this->m_pObj2[pos])
					{
						std::cout << "[TestDynMemPool] error in Allocate" << std::endl;
						continue;
					}
					this->m_pObj2[pos]->setValue(2000000 + pos);
				}
				break;
			case 3:
				{
					if(this->m_pObj3[pos])
					{
						continue;
					}
					if(pool)
					{
						this->m_pObj3[pos] = (TestObj_3*)CDynMemPool::GetInstance().Allocate(sizeof(TestObj_3));
					}
					else
					{
						this->m_pObj3[pos] = (TestObj_3*)malloc(sizeof(TestObj_3));
					}
					if(!this->m_pObj3[pos])
					{
						std::cout << "[TestDynMemPool] error in Allocate" << std::endl;
						continue;
					}
					this->m_pObj3[pos]->setValue(3000000 + pos);
				}
				break;
			case 4:
				{
					if(this->m_pObj4[pos])
					{
						continue;
					}
					if(pool)
					{
						this->m_pObj4[pos] = (TestObj_4*)CDynMemPool::GetInstance().Allocate(sizeof(TestObj_4));
					}
					else
					{
						this->m_pObj4[pos] = (TestObj_4*)malloc(sizeof(TestObj_4));
					}
					if(!this->m_pObj4[pos])
					{
						std::cout << "[TestDynMemPool] error in Allocate" << std::endl;
						continue;
					}
					this->m_pObj4[pos]->setValue(4000000 + pos);
				}
				break;
			}
		}
	}
}

/// 释放空间
void TestDynMemPool::Dealloc(int type, bool pool)
{
	size_t num = 1;
	size_t choose = 0;

	switch(type)
	{
	case __TYPE_RAND:
		{
			/// 1 ~ 5
			num = (rand() % 5) + 1;
			choose = (rand() % 4) + 1;
		}
		break;
	case __TYPE_EVERY:
		{
			num = 1;
			choose = 0;
		};
		break;
	default:
		return;
	}

	if(choose == 0)
	{
		size_t pos = 0;
		for(; pos < obj_num[0]; ++pos)
		{
			if(!this->m_pObj1[pos])
			{
				continue;
			}
			if(pool)
			{
				if(!CDynMemPool::GetInstance().Deallocate(this->m_pObj1[pos], sizeof(TestObj_1)))
				{
					std::cout << "[TestDynMemPool] error in Deallocate" << std::endl;
					continue;
				}
			}
			else
			{
				free(this->m_pObj1[pos]);
			}
			this->m_pObj1[pos] = NULL;
		}

		pos = 0;
		for(; pos < obj_num[1]; ++pos)
		{
			if(!this->m_pObj2[pos])
			{
				continue;
			}
			if(pool)
			{
				if(!CDynMemPool::GetInstance().Deallocate(this->m_pObj2[pos], sizeof(TestObj_2)))
				{
					std::cout << "[TestDynMemPool] error in Deallocate" << std::endl;
					continue;
				}
			}
			else
			{
				free(this->m_pObj2[pos]);
			}
			this->m_pObj2[pos] = NULL;
		}

		pos = 0;
		for(; pos < obj_num[2]; ++pos)
		{
			if(!this->m_pObj3[pos])
			{
				continue;
			}
			if(pool)
			{
				if(!CDynMemPool::GetInstance().Deallocate(this->m_pObj3[pos], sizeof(TestObj_3)))
				{
					std::cout << "[TestDynMemPool] error in Deallocate" << std::endl;
					continue;
				}
			}
			else
			{
				free(this->m_pObj3[pos]);
			}
			this->m_pObj3[pos] = NULL;
		}

		pos = 0;
		for(; pos < obj_num[3]; ++pos)
		{
			if(!this->m_pObj4[pos])
			{
				continue;
			}
			if(pool)
			{
				if(!CDynMemPool::GetInstance().Deallocate(this->m_pObj4[pos], sizeof(TestObj_4)))
				{
					std::cout << "[TestDynMemPool] error in Deallocate" << std::endl;
					continue;
				}
			}
			else
			{
				free(this->m_pObj4[pos]);
			}
			this->m_pObj4[pos] = NULL;
		}
	}
	else
	{
		/// 每个都做
		size_t pos = 0;
		for(; pos < obj_num[choose-1]; ++pos)
		{
			if(pos % num != 0)
			{
				continue;
			}

			switch(choose)
			{
			case 1:
				{
					if(!this->m_pObj1[pos])
					{
						continue;
					}
					if(pool)
					{
						if(!CDynMemPool::GetInstance().Deallocate(this->m_pObj1[pos], sizeof(TestObj_1)))
						{
							std::cout << "[TestDynMemPool] error in Deallocate" << std::endl;
							continue;
						}
					}
					else
					{
						free(this->m_pObj1[pos]);
					}
					this->m_pObj1[pos] = NULL;
				}
				break;
			case 2:
				{
					if(!this->m_pObj2[pos])
					{
						continue;
					}
					if(pool)
					{
						if(!CDynMemPool::GetInstance().Deallocate(this->m_pObj2[pos], sizeof(TestObj_2)))
						{
							std::cout << "[TestDynMemPool] error in Deallocate" << std::endl;
							continue;
						}
					}
					else
					{
						free(this->m_pObj2[pos]);
					}
					this->m_pObj2[pos] = NULL;
				}
				break;
			case 3:
				{
					if(!this->m_pObj3[pos])
					{
						continue;
					}
					if(pool)
					{
						if(!CDynMemPool::GetInstance().Deallocate(this->m_pObj3[pos], sizeof(TestObj_3)))
						{
							std::cout << "[TestDynMemPool] error in Deallocate" << std::endl;
							continue;
						}
					}
					else
					{
						free(this->m_pObj3[pos]);
					}
					this->m_pObj3[pos] = NULL;
				}
				break;
			case 4:
				{
					if(!this->m_pObj4[pos])
					{
						continue;
					}
					if(pool)
					{
						if(!CDynMemPool::GetInstance().Deallocate(this->m_pObj4[pos], sizeof(TestObj_4)))
						{
							std::cout << "[TestDynMemPool] error in Deallocate" << std::endl;
							continue;
						}
					}
					else
					{
						free(this->m_pObj4[pos]);
					}
					this->m_pObj4[pos] = NULL;
				}
				break;
			}
		}
	}
}

/// 暴力测试
void TestDynMemPool::ViolenceTest(size_t n, int type, bool pool)
{
	size_t pos = 0;
	for(; pos < n; ++pos)
	{
		this->Alloc(type, pool);
		this->Dealloc(type, pool);
	}
}
